#include "stdafx.h"
#include "CoreDatabase.h"
#include "Account.h"
#include "Character.h"

CCoreDatabase::CCoreDatabase(CDatabaseSettings* settings)
	: m_settings(settings)
{
}

CCoreDatabase::~CCoreDatabase()
{
	m_dbc.close();

	FOR_EACH (m_accounts, i)
	{
		delete m_accounts[i];
	}
	m_accounts.clear();

	m_settings = null;
}

bool CCoreDatabase::init()
{
	if (!m_dbc.connect(m_settings->Host.c_str(), m_settings->Port,
		m_settings->User.c_str(), m_settings->Password.c_str(),
		m_settings->Database.c_str()))
	{
		CConsole::print(" Can't connect to Database: %s\n", m_dbc.getError());
		return false;
	}

	return true;
}

CAccount* CCoreDatabase::getAccount(const char *name)
{
	// on passe d'abord le nom en lowercase
	char lowername[42];
	memset(lowername, 0, 42);
	const int nameLenght = strlen(name);
	for(int i = 0; i < nameLenght; i++)
		lowername[i] = tolower(name[i]);

	FOR_EACH (m_accounts, i)
	{
		if (m_accounts[i]->m_username.compare(lowername) == 0)
			return m_accounts[i];
	}

	CQueryResult result;

	if (m_dbc.query(
		"SELECT id, password, accesslevel, bantime FROM accounts "
		"WHERE username='%s' LIMIT 1",
		xescape(lowername).c_str()) &&
		m_dbc.getResult(result))
	{
		if (result.nextRow())
		{
			CAccount* account = new CAccount();
			account->m_id = result.getFieldS32(0);
			account->m_username = lowername;
			account->m_password = result.getFieldString(1);
			account->m_access = E_ACCESS_LEVEL(result.getFieldS32(2));
			account->m_bantime = result.getFieldS64(3);

			m_accounts.push_back(account);
			return account;
		}
	}

	return null;
}

void CCoreDatabase::loadCharacters(CAccount* account)
{
	account->solve();

	CQueryResult result;
	CCharacter* character = null;

	if (m_dbc.query(
		"SELECT id, name, place, sex, job, hair, hairColor, face, stat_FOR, stat_END, stat_DEX, stat_INT, level FROM characters WHERE account='%u';",
		account->m_id) &&
		m_dbc.getResult(result))
	{
		while(result.nextRow())
		{
			character = new CCharacter();

			character->m_id = result.getFieldS32(0);
			character->m_name = result.getFieldString(1);
			character->m_place = Limit(result.getFieldS32(2), 0, 2);
			character->m_sex = static_cast<E_SEX>(result.getFieldS32(3));
			character->m_job = static_cast<E_JOB>(result.getFieldS32(4));
			character->m_hair = result.getFieldS32(5);
			character->m_hairColor = result.getFieldS32(6);
			character->m_face = result.getFieldS32(7);
			character->m_FOR = result.getFieldS32(8);
			character->m_END = result.getFieldS32(9);
			character->m_DEX = result.getFieldS32(10);
			character->m_INT = result.getFieldS32(11);
			character->m_level = result.getFieldS32(12);

			account->m_characters[character->m_place] = character;
		}
	}

	for(int i = 0; i < 3; i++)
	{
		character = account->m_characters[i];
		if(character && m_dbc.query(
			"SELECT itemid FROM items WHERE characterid='%u' and type='1' and place>'41' ORDER BY place ASC;",
			character->m_id) &&
			m_dbc.getResult(result))
		{
			while(result.nextRow())
			{
				character->m_equipment.push_back(result.getFieldS32(0));
			}
		}
	}
}

bool CCoreDatabase::characterExists(const char* name)
{
	CQueryResult result;

	if (m_dbc.query(
		"SELECT id FROM characters WHERE name='%s';",
		name) &&
		m_dbc.getResult(result))
	{
		if(result.nextRow())
		{
			return true;
		}
	}

	return false;
}

CCharacter* CCoreDatabase::createCharacter(CAccount* account, byte place, const char* name, byte hair, int hairColor, byte sex, byte face, int bankpass)
{
	CQueryResult result;

	m_dbc.query("INSERT INTO characters(account, name, place, sex, hair, hairColor, face, bankpass) VALUES('%u', '%s', '%u', '%u', '%u', '%d', '%u', '%u');",
		account->m_id, name, place, sex, hair, hairColor, face, bankpass);

	if (m_dbc.query(
		"SELECT id, job, stat_FOR, stat_END, stat_DEX, stat_INT, level FROM characters WHERE account='%u' AND place='%u';",
		account->m_id, place) &&
		m_dbc.getResult(result))
	{
		if(result.nextRow())
		{
			CCharacter* character = account->m_characters[place] = new CCharacter();

			character->m_id = result.getFieldS32(0);
			character->m_name = name;
			character->m_place = place;
			character->m_sex = static_cast<E_SEX>(sex);
			character->m_job = static_cast<E_JOB>(result.getFieldS32(1));
			character->m_hair = hair;
			character->m_hairColor = hairColor;
			character->m_face = face;
			character->m_FOR = result.getFieldS32(2);
			character->m_END = result.getFieldS32(3);
			character->m_DEX = result.getFieldS32(4);
			character->m_INT = result.getFieldS32(5);
			character->m_level = result.getFieldS32(6);

			return character;
		}
	}

	return null;
}

void CCoreDatabase::deleteCharacter(CAccount* account, int id)
{
	for(int i = 0; i < 3; i++)
	{
		if(account->m_characters[i] && account->m_characters[i]->m_id == id)
		{
			m_dbc.query("UPDATE characters SET account='%d' WHERE id='%u' LIMIT 1",
				-(account->m_id),
				id);

			stringc e = m_dbc.getError();

			delete account->m_characters[i];
			account->m_characters[i] = null;
			return;
		}
	}
}

void CCoreDatabase::createItem(CCharacter* character, int place, int itemId, int count)
{
	m_dbc.query("INSERT INTO items(characterid, place, itemid, count) VALUES('%u', '%u', '%u', '%u');",
		character->m_id, place, itemId, count);

	if(place > 41)
		character->m_equipment.push_back(itemId);
}